package com.gcloud.mesh.monitor.service;

import com.gcloud.mesh.dcs.service.AppService;
import com.gcloud.mesh.header.enums.MonitorMeter;
import com.gcloud.mesh.header.msg.monitor.StatisticsMsg;
import com.gcloud.mesh.header.vo.monitor.SampleVo;
import com.gcloud.mesh.header.vo.monitor.StatisticsPointVo;
import com.gcloud.mesh.header.vo.monitor.StatisticsResourceVo;
import com.gcloud.mesh.header.vo.monitor.StatisticsVo;
import com.gcloud.mesh.monitor.dao.StatisticsDao;
import com.gcloud.mesh.monitor.entity.StatisticsEntity;
import com.gcloud.mesh.redis.MockRedis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.security.SecureRandom;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

@Service
public class StatisticsCheatService {

	@Autowired
	private MockRedis<String> redis;

	@Autowired
	private AppService appService;

	@Autowired
	private StatisticsDao statisticsDao;

	private static final SimpleDateFormat monitorSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	public StatisticsVo statistics(StatisticsMsg msg) {
		StatisticsVo res = new StatisticsVo();
		List<StatisticsResourceVo> list = new ArrayList<StatisticsResourceVo>();
		StatisticsResourceVo vo = new StatisticsResourceVo();
		List<StatisticsPointVo> points = new ArrayList<StatisticsPointVo>();

		String meter = msg.getMeter();
		String resourceId = msg.getResourceId();

		List<StatisticsEntity> StatisticsData = statisticsDao.getData(meter, resourceId);

		if (StatisticsData != null && StatisticsData.size() > 0) {
			for (int i = 0; i < StatisticsData.size(); i++) {
				StatisticsPointVo point = new StatisticsPointVo();
				point.setTime(monitorSdf.format(StatisticsData.get(i).getTimestamp()));
				point.setValue(StatisticsData.get(i).getValue());
				points.add(point);
			}
		} else {
			for (int i = 0; i < 60; i++) {
				StatisticsPointVo point = new StatisticsPointVo();
				point.setTime(msg.getEndTime());

				String value = redis.getMonitorData(meter, resourceId);
				if (value == null || value.equals("0.0")) {
					value = MonitorMeter.getByMeter(meter).getValue();
				}
				Double dou = Double.parseDouble(value) * random();
				BigDecimal b = new BigDecimal(dou);
				double d = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
				// redis.setMonitorData(meter, resourceId, d + "");

				if (overload(meter, d)) {
					d = clearAndInitData(meter, resourceId);
				}

				point.setValue(d);
				points.add(point);
			}
		}

		vo.setPoints(points);
		vo.setResourceId(resourceId);
		list.add(vo);
		res.setList(list);

		return res;
	}

	public boolean requestStatistics() {

		return true;
	}

	public String latestSample(String meter, String resourceId) {

		String value = redis.getMonitorData(meter, resourceId);
		if (value == null || value.equals("0.0")) {
			value = MonitorMeter.getByMeter(meter).getValue();
		}
		// Double dou = Double.parseDouble(value) * random();
		Double dou = Double.parseDouble(value);
		BigDecimal b = new BigDecimal(dou);
		double d = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
		// redis.setMonitorData(meter, resourceId, d + "");

		if (overload(meter, d)) {
			d = clearAndInitData(meter, resourceId);
		}

		// 数据中心指标根据云资源数量波动
		if (meter.contains("environment.") || meter.contains("datacenter.")) {
			// PUE特殊处理
			if (meter.contains("datacenter.pue")) {
				String datacenterPower = redis.getMonitorData("datacenter.power", resourceId);
				Double dp = Double.parseDouble(datacenterPower);
				BigDecimal dpb = new BigDecimal(dp);
				double dpd = dpb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

				String itPower = redis.getMonitorData("datacenter.it_power", resourceId);
				Double ip = Double.parseDouble(itPower);
				BigDecimal ipb = new BigDecimal(ip);
				double ipd = ipb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

				d = dpd / ipd;
			}
			int size = appService.conutInstance(resourceId);
			d = (d * (1 + (float) (size * 0.1)));
		}

		return round(d);
	}

	public List<SampleVo> latestSamples(String meter, String resourceId) {
		List<SampleVo> res = new ArrayList<SampleVo>();

		List<MonitorMeter> meters = MonitorMeter.getTypeByName(meter);
		for (MonitorMeter type : meters) {
			SampleVo vo = new SampleVo();

			Double volume = 0.0;
			String value = redis.getMonitorData(type.getMeter(), resourceId);
			if (value == null || value.equals("0.0")) {
				value = MonitorMeter.getByMeter(type.getMeter()).getValue();
			}

			volume = Double.parseDouble(value);
			// volume = Double.parseDouble(value) * random();
			BigDecimal b = new BigDecimal(volume);
			double d = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

			// redis.setMonitorData(type.getMeter(), resourceId, d + "");

			if (overload(type.getMeter(), d)) {
				d = clearAndInitData(type.getMeter(), resourceId);
			}

			// 数据中心指标根据云资源数量波动
			if (meter.contains("environment.") || meter.contains("datacenter.")) {
				// PUE特殊处理
				if (meter.contains("datacenter.pue")) {
					String datacenterPower = redis.getMonitorData("datacenter.power", resourceId);
					Double dp = Double.parseDouble(datacenterPower);
					BigDecimal dpb = new BigDecimal(dp);
					double dpd = dpb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

					String itPower = redis.getMonitorData("datacenter.it_power", resourceId);
					Double ip = Double.parseDouble(itPower);
					BigDecimal ipb = new BigDecimal(ip);
					double ipd = ipb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

					d = dpd / ipd;
				}
				int size = appService.conutInstance(resourceId);
				d = (d * (1 + (float) (size * 0.1)));
			}

			vo.setVolume(d);
			vo.setMeter(type.getMeter());
			vo.setUnit(type.getUnit());

			res.add(vo);
		}
		return res;
	}

	private float random() {

		SecureRandom random = new SecureRandom();
		int value = random.nextInt(5) + 98;
		float res = (float) (value * 0.01);

		return res;
	}

	private String round(double b) {
		DecimalFormat df = new DecimalFormat("#.00");
		return df.format(b);
	}

	public double clearAndInitData(String meter, String resourceId) {
		Double volume = 0.0;
		String value = MonitorMeter.getByMeter(meter).getValue();

		volume = Double.parseDouble(value) * random();

		BigDecimal b = new BigDecimal(volume);
		double d = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

		redis.setMonitorData(meter, resourceId, d + "");

		return d;
	}

	public boolean overload(String meter, Double value) {
		MonitorMeter monitorMeter = MonitorMeter.getByMeter(meter);
		if (value < monitorMeter.getStart() || value > monitorMeter.getEnd()) {
			return true;
		}
		return false;
	}
}
